<?php
/**
 * 数据库文件备份为json文件
 */
class BackUpToJson
{
    /**
     * 错误信息
     *
     * @var mixed
     */
    public $error;

    /**
     * 数据库一次取的数据量
     *
     * @var int
     */
    private $num = 50;

    /**
     * 数据库操作
     *
     * @var object
     */
    private $db;

    /**
     * 未压缩json文件
     *
     * @var string
     */
    private $filename;

    /**
     * 压缩后的文件
     *
     * @var string
     */
    private $zipname;

    /**
     * 需要备份的数据表
     * 
     * @var array
     */
    private $_types = array(
        'contents',
        'comments',
        'metas',
        'relationships',
        'users',
        'fields',
        'options'
    );

    /**
     * 构造函数,初始化组件
     *
     * @access public
     */
    public function __construct()
    {
        /** 初始化数据库 */
        $this->db = Typecho_Db::get();
    }

    /**
     * 获取数据库数据
     *
     * @return array
     */
    private function getArray()
    {
        $data = array();
        $db = $this->db;
        
        foreach ($this->_types as $type) {
            $page = 1;
            do {
                $rows = $db->fetchAll($db->select()->from('table.' . $type)->page($page, $this->num));
                $page ++;

                foreach ($rows as $row) {
                    $data[$type][] = $row;
                }
            } while (count($rows) == $this->num);
        }
        return $data;
    }

    /**
     * 写文件
     *
     * @return bool/string
     */
    public function write()
    {
        $data = json_encode($this->getArray());
        $this->filename = dirname(__FILE__) . '/tmp/' . $this->generateRandomString(20);
        if (!file_put_contents($this->filename, $data)) {
            $this->error = '写入json文件错误';
            return false;
        }

        $zip = new ZipArchive();
        $this->zipname = $this->filename . '.zip';
        if ($zip->open($this->zipname, ZIPARCHIVE::CREATE) !== TRUE) {
            $this->error = '创建压缩文件错误';
            return false;
        }
        if (!$zip->addFile($this->filename, '/data.json')) {
            $this->error = '添加压缩文件错误';
            return false;
        }
        $zip->close();
        return $this->zipname;
    }

    /**
     * 清理临时文件
     *
     * @return void
     */
    public function clean()
    {
        if (!empty($this->filename) && file_exists($this->filename)) {
            if(!unlink($this->filename)) {
                $this->error = '删除json文件失败';
            }
        }
        if (!empty($this->zipname) && file_exists($this->zipname)) {
            if(!unlink($this->zipname)) {
                $this->error = '删除压缩文件失败';
            }
        }
    }

    /**
     * 生成随机文件名
     *
     * @param int $length 文件名长度
     * @return string
     */
    protected function generateRandomString($length = 10) { 
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
        $randomString = ''; 
        for ($i = 0; $i < $length; $i++) { 
            $randomString .= $characters[rand(0, strlen($characters) - 1)]; 
        } 
        return $randomString; 
    }
}